package ajakuulauku;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * Handles the current level's data.
 * 
 */
public class CurrentLevel {
	public static boolean hasEdges = true;
	
	public static HashMap<String, ArrayList<GameObject>>objectCollections = new HashMap<String, ArrayList<GameObject>>();
	
	private static double[][] a_magnets, a_pillars, a_balls, a_holes;
	/**
	 * List of magnets in current level.
	 */
	public static ArrayList<Magnet> magnets = new ArrayList<Magnet>();
	/**
	 * List of pillars in current level
	 */
	public static ArrayList<Pillar> pillars = new ArrayList<Pillar>();
	/**
	 * List of Balls in current level.
	 */
	public static ArrayList<Ball> balls = new ArrayList<Ball>();
	/**
	 * Hole of current level.
	 */
	public static ArrayList<Hole> holes = new ArrayList<Hole>();
	/**
	 * List of all objects that ball can collide with.
	 */
	public static ArrayList<GameObject> allObjects = new ArrayList<GameObject>();
	/**
	 * Set of indexes of currently activated magnets.
	 */
	public static Set<Integer> activated = new HashSet<Integer>();
	/**
	 * Friction.
	 */
	public static Double friction;
	
	public static GameObject createGameObject(String name) {
		Class [] classParm = null;
		Object [] objectParm = null;
		String className = "ajakuulauku." + capitalize(name);
		//System.out.println(className);

		try {
			Class cl = Class.forName(className);
			java.lang.reflect.Constructor co = cl.getConstructor(classParm);
			return (GameObject)co.newInstance(objectParm);
		}catch (Exception e) {
			//e.printStackTrace();
			return null;
		}
	}
	
	public static String capitalize(String word) {
		String firstLetter = word.substring(0,1);  // Get first letter
        String remainder   = word.substring(1);    // Get remainder of word.
        String capitalized = firstLetter.toUpperCase() + remainder.toLowerCase();
        return capitalized;
	}
	
	/**
	 * Loads the level's objects and other data read from XML.
	 * @param levelName name of current level
	 */
	public static void envalue(String levelName) {
		/*ArrayList<Object> allData = XMLMaster.read(levelName);
		a_magnets = (double[][]) allData.get(0);
		a_pillars = (double[][]) allData.get(1);
		a_balls = (double[][]) allData.get(2);
		a_holes = (double[][]) allData.get(3);
		friction = Double.parseDouble(allData.get(4).toString());
		parseToObjects();*/
		XMLReader reader = new XMLReader(levelName);
		ArrayList<XMLElement> objects = reader.parse();
		for(XMLElement obj : objects) {
			if(obj.name == "other") {
				System.out.println(obj.params);
				friction = Double.parseDouble(obj.params.get("friction"));
			}
		}
		for(XMLElement obj : objects) {
			GameObject tmp = createGameObject(obj.name);
			if (tmp == null)
				continue;
			for(String paramName : obj.params.keySet()) {
				tmp.parseParam(paramName, obj.params.get(paramName));
			}
			tmp.parseParam("friction", friction.toString());
			tmp.finishCreating();
			addObject(obj.name, tmp);
		}
	}
	
	public static void addObject(String name, GameObject obj) {
		allObjects.add(obj);
		if(!objectCollections.containsKey(name))
			objectCollections.put(name, new ArrayList<GameObject>());
		objectCollections.get(name).add(obj);
	}
	
	/**
	 * Resets the level's data.
	 */
	public static void resetLevel() {
	   activated.clear();
	   magnets.clear();
	   pillars.clear();
	   balls.clear();
	   holes.clear();
	   allObjects.clear();
	   objectCollections.clear();
	   friction = 0d;
	}
	
	/**
	 * Adds pillar with coordinates x and y to the level.
	 * @param x
	 * @param y
	 */
	public static void addPillar(double x, double y) {
		Pillar tmp = new Pillar(x, y, 20);
		pillars.add(tmp);
		allObjects.add(tmp);
	}
	
	/**
	 * Adds magnet with coordinates x and y to the level.
	 * @param x
	 * @param y
	 */
	public static void addMagnet(double x, double y) {
		Magnet tmp = new Magnet(x, y, 20, 1500);
		magnets.add(tmp);
		allObjects.add(tmp);
	}
	
	/**
	 * Adds a ball with coordinates x and y to the level.
	 * @param a Ball
	 */
	public static void addBall(double x, double y) {
		Ball tmp = new Ball(x, y, 20, 1);
		balls.add(tmp);
		allObjects.add(tmp);
	}
	
	/**
	 * Adds a hole with coordinates x and y to the level.
	 * @param x
	 * @param y
	 */
	public static void addHole(double x, double y) {
		Hole tmp = new Hole(x, y, 20);
		holes.add(tmp);
		allObjects.add(tmp);
	}
	
	/**
	 * Creates objects from data read from XML.
	 */
	private static void parseToObjects() {
		for (int i = 0; i < a_magnets.length; i++) {
			addMagnet(a_magnets[i][0], a_magnets[i][1]);
			// TODO: figure out where magnet force should be
		}
		for (int i = 0; i < a_pillars.length; i++) {
			addPillar(a_pillars[i][0], a_pillars[i][1]);
		}
		
		for (int i = 0; i < a_balls.length; i++) {
			addBall(a_balls[0][0], a_balls[0][1]);
		}
		// TODO: find out where to keep mass and friction
		for (int i = 0; i < a_holes.length; i++) {
			addHole(a_holes[0][0], a_holes[0][1]);
		}
	}
}
